﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Diagnostics;
using System.Collections;

using TDB.LinqSerializer;
using TDB.DBInternals;

namespace TDB.Communication
{
  public class QueryService : IQueryService
  {
    public IEnumerable Get(string databasename, Expression filter)
    {
      Type type = null;
      var result = ExecuteFilter(databasename, filter, out type);
      return result;
    }

    public IEnumerable XGet(string databasename, System.Xml.Linq.XElement filterexpression)
    {
      return Get(databasename, filterexpression.Deserialize());
    }

    private IEnumerable ExecuteFilter(string databasename, Expression filter, out Type entitytype)
    {
      while (filter.CanReduce)
        filter = filter.Reduce();

      entitytype = (Type)null;
      if (filter.NodeType == ExpressionType.Lambda)
      {
        var lfilter = filter as LambdaExpression;
        if (lfilter.Parameters.Count > 0)
          entitytype = lfilter.Parameters[0].Type;
      }

      if (entitytype != null)
      {
        var tt = this.GetType();
        var method = tt.GetMethod("ExecuteFilterGeneric", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        var gmethod = method.MakeGenericMethod(entitytype);
        var result = gmethod.Invoke(this, new object[] { databasename, filter as LambdaExpression });
        return result as IEnumerable;
      }
      return null;
    }

    private IEnumerable ExecuteFilterGeneric<T>(string databasename, LambdaExpression filter)
    {
      var texpression = filter as Expression<Func<T, bool>>;
      if (texpression != null)
      {
        var store = StoreManager.GetStore<T>(databasename);
        return store.Where(texpression.Compile());

      }
      return null;
    }


  }
}
